package com.sojson.util.file;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.sojson.entity.bo.FileTable;
import com.sojson.entity.po.FileDepot;
import com.sojson.util.SpringUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.file.enums.EFileTableBase;
import com.sojson.util.file.interfaces.FileDepotUtilInterface;
import com.sojson.util.file.interfaces.FileTableInterface;

import lombok.extern.slf4j.Slf4j;

/**
 * 文件库工具类
 * 
 * @author liu
 * @date 2021-05-26
 */
@Slf4j
public class FileDepotUtil {

    private static FileDepotUtilInterface fileDepotUtil = SpringUtil.getBeanByType(FileDepotUtilInterface.class);
    public static List<FileTable> fileTables = new ArrayList<>();

    static {
        EFileTableBase[] values = EFileTableBase.values();
        for (EFileTableBase eFileTable : values) {
            fileTables.add(new FileTable(eFileTable));
        }
    }

    /**
     * 添加文件(本地文件)
     * 
     * @param newImg 上传接口返回的字符串
     */
    public static boolean uploadThisLocal(String newImg) {
        return fileDepotUtil.uploadThisLocal(newImg);
    }

    /**
     * 添加文件(文件存储系统文件)
     * 
     * @param newImg 上传接口返回的字符串
     */
    public static boolean upload(String newImg) {
        return fileDepotUtil.upload(newImg);
    }

    /**
     * 添加数据的时候修改文件(异步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static void insert(int tableCode, String fieldName, String newImg) {
        fileDepotUtil.insert(tableCode, fieldName, newImg);
    }

    /**
     * 添加数据的时候修改文件(同步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static boolean insertSync(int tableCode, String fieldName, String newImg) {
        return fileDepotUtil.insertSync(tableCode, fieldName, newImg);
    }

    /**
     * 添加数据的时候修改文件(异步方法)
     * 
     * @param fileTable
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static void insert(FileTableInterface fileTable, String fieldName, String newImg) {
        fileDepotUtil.insert(fileTable.getCode(), fieldName, newImg);
    }

    /**
     * 添加数据的时候修改文件(同步方法)
     * 
     * @param fileTable
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static boolean insertSync(FileTableInterface fileTable, String fieldName, String newImg) {
        return fileDepotUtil.insertSync(fileTable.getCode(), fieldName, newImg);
    }

    /**
     * 添加数据的时候修改文件(异步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static void insertList(int tableCode, String fieldName, String newImg) {
        fileDepotUtil.insertList(tableCode, fieldName, newImg);
    }

    /**
     * 添加数据的时候修改文件(同步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static int insertListSync(int tableCode, String fieldName, String newImg) {
        return fileDepotUtil.insertListSync(tableCode, fieldName, newImg);
    }

    /**
     * 添加数据的时候修改文件(异步方法)
     * 
     * @param fileTable
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static void insertList(FileTableInterface fileTable, String fieldName, String newImg) {
        fileDepotUtil.insertList(fileTable.getCode(), fieldName, newImg);
    }

    /**
     * 添加数据的时候修改文件(同步方法)
     * 
     * @param fileTable
     * @param fieldName 字段名
     * @param newImg    上传接口返回的字符串
     */
    public static int insertListSync(FileTableInterface fileTable, String fieldName, String newImg) {
        return fileDepotUtil.insertListSync(fileTable.getCode(), fieldName, newImg);
    }

    /**
     * 修改数据的时候修改文件(异步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static void update(int tableCode, String fieldName, String newImg, String oldImg) {
        fileDepotUtil.update(tableCode, fieldName, newImg, oldImg);
    }

    /**
     * 修改数据的时候修改文件(同步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static boolean updateSync(int tableCode, String fieldName, String newImg, String oldImg) {
        return fileDepotUtil.updateSync(tableCode, fieldName, newImg, oldImg);
    }

    /**
     * 修改数据的时候修改文件(异步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static void updateList(int tableCode, String fieldName, String newImg, String oldImg) {
        fileDepotUtil.updateList(tableCode, fieldName, newImg, oldImg);
    }

    /**
     * 修改数据的时候修改文件(同步方法)
     * 
     * @param tableCode 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static boolean updateListSync(int tableCode, String fieldName, String newImg, String oldImg) {
        return fileDepotUtil.updateListSync(tableCode, fieldName, newImg, oldImg);
    }

    /**
     * 修改数据的时候修改文件(异步方法)
     * 
     * @param fileTable 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static void update(FileTableInterface fileTable, String fieldName, String newImg, String oldImg) {
        fileDepotUtil.update(fileTable.getCode(), fieldName, newImg, oldImg);
    }

    /**
     * 修改数据的时候修改文件(同步方法)
     * 
     * @param fileTable 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static boolean updateSync(FileTableInterface fileTable, String fieldName, String newImg, String oldImg) {
        return fileDepotUtil.updateSync(fileTable.getCode(), fieldName, newImg, oldImg);
    }

    /**
     * 修改数据的时候修改文件(异步方法)
     * 
     * @param fileTable 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static void updateList(FileTableInterface fileTable, String fieldName, String newImg, String oldImg) {
        fileDepotUtil.updateList(fileTable.getCode(), fieldName, newImg, oldImg);
    }

    /**
     * 修改数据的时候修改文件(同步方法)
     * 
     * @param fileTable 表代码
     * @param fieldName 字段名
     * @param newImg    新文件
     * @param oldImg    旧文件
     */
    public static boolean updateListSync(FileTableInterface fileTable, String fieldName, String newImg, String oldImg) {
        return fileDepotUtil.updateListSync(fileTable.getCode(), fieldName, newImg, oldImg);
    }

    /**
     * 删除数据的时候修改文件(异步方法)
     * 
     * @param oldImg 旧文件
     */
    public static void delete(String oldImg) {
        fileDepotUtil.delete(oldImg);
    }

    /**
     * 删除数据的时候修改文件(同步方法)
     * 
     * @param oldImg 旧文件
     */
    public static boolean deleteSync(String oldImg) {
        return fileDepotUtil.deleteSync(oldImg);
    }

    /**
     * 删除数据的时候修改文件(异步方法)
     * 
     * @param oldImg 旧文件
     */
    public static void deleteList(String oldImg) {
        fileDepotUtil.deleteList(oldImg);
    }

    /**
     * 删除数据的时候修改文件(同步方法)
     * 
     * @param oldImg 旧文件
     */
    public static int deleteListSync(String oldImg) {
        return fileDepotUtil.deleteListSync(oldImg);
    }

    /**
     * 删除数据的时候修改文件(异步方法)
     * 
     * @param oldImg 旧文件
     */
    public static void deleteList(String[] oldImg) {
        fileDepotUtil.deleteList(oldImg);
    }

    /**
     * 删除数据的时候修改文件(同步方法)
     * 
     * @param oldImg 旧文件
     */
    public static int deleteListSync(String[] oldImg) {
        return fileDepotUtil.deleteListSync(oldImg);
    }

    /**
     * 删除数据的时候修改文件(异步方法)
     * 
     * @param oldImg 旧文件
     */
    public static void deleteList(List<String> oldImg) {
        fileDepotUtil.deleteList(oldImg);
    }

    /**
     * 删除数据的时候修改文件(同步方法)
     * 
     * @param oldImg 旧文件
     */
    public static int deleteListSync(List<String> oldImg) {
        return fileDepotUtil.deleteListSync(oldImg);
    }

    /**
     * 删除数据的时候修改文件(异步方法)
     * 
     * @param oldImg 旧文件
     */
    public static void deleteLists(List<String> oldImg) {
        fileDepotUtil.deleteLists(oldImg);
    }

    /**
     * 删除数据的时候修改文件(同步方法)
     * 
     * @param oldImg 旧文件
     */
    public static int deleteListsSync(List<String> oldImg) {
        return fileDepotUtil.deleteListsSync(oldImg);
    }

    /**
     * 删除数据
     */
    public static int deleteData() {
        return fileDepotUtil.deleteData();
    }

    /**
     * 删除本地的文件
     * 
     * @param url
     */
    public static void deleteFileThisLocalByUrl(String url) {
        if (isBlank(url)) {
            return;
        }

        String path = url.substring(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE_URL.length());
        File file = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + path);
        // 删除文件
        boolean delete = file.delete();
        // 如果删除成功或者文件不存在就将文件添加到删除列表中
        if (delete || !file.exists()) {
            fileDepotUtil.deleteFile(url);
        }
    }

    /**
     * 删除本地的文件
     * 
     * @param urls
     */
    public static void deleteFileThisLocalByUrl(List<String> urls) {
        for (String url : urls) {
            try {
                deleteFileThisLocalByUrl(url);
            } catch (Exception e) {
                log.error("删除旧文件失败: " + e.getMessage());
            }
        }
    }

    /**
     * 删除存储系统的文件
     * 
     * @param path
     */
    public static void deleteFile(String url) {
        if (isBlank(url)) {
            return;
        }
        // TODO
    }

    /**
     * 删除本地的文件
     * 
     * @param urls
     */
    public static void deleteFile(List<String> urls) {
        for (String url : urls) {
            try {
                deleteFile(url);
            } catch (Exception e) {
                log.error("删除旧文件失败: " + e.getMessage());
            }
        }
    }

    /**
     * 删除文件
     * 
     * @param list
     */
    public static void deleteFileList(List<FileDepot> images) {
        int size = images.size();
        if (size == 0) {
            return;
        }

        FileDepot path = null;
        File file = null;
        boolean delete = false;
        // 删除多少个文件后修改状态
        int count = 1000;
        // 要删除的文件列表
        List<String> deleteList = new ArrayList<>();
        int i = 0;
        while (i < size) {
            // 获取文件路径
            path = images.get(i);
            // 获取文件对象
            file = new File(FileUtil.THIS_LOCALITY_DIRECTORY_BUCKET_NAME_BASE + path.getPath());
            // 删除文件
            delete = file.delete();
            // 如果删除成功或者文件不存在就将文件添加到删除列表中
            if (delete || !file.exists()) {
                deleteList.add(path.getUrl());
            }

            i++;
            // 每删除到一定数量就将数据的状态修改为未引用
            if (i % count == 0) {
                try {
                    fileDepotUtil.deleteFile(deleteList);
                } catch (Exception e) {
                    log.error("删除旧文件失败: " + e.getMessage());
                }
                deleteList.clear();
            }
        }

        // 修改剩下的数据为未引用
        if (deleteList.size() > 0) {
            try {
                fileDepotUtil.deleteFile(deleteList);
            } catch (Exception e) {
                log.error("删除旧文件失败: " + e.getMessage());
            }
            deleteList.clear();
        }
    }

    /**
     * 判断一个字符串是否是空(空对象和空字符串)
     * 
     * @param str
     * @return
     */
    private static boolean isBlank(Object img) {
        return StringUtil.isBlank(img);
    }

}